package com.css.fxfzypg.modules.rating.library.service;

import cn.hutool.core.util.IdUtil;
import com.css.fxfzypg.modules.rating.library.dao.*;
import com.css.fxfzypg.modules.rating.library.model.dto.*;
import com.css.fxfzypg.modules.rating.library.model.entity.*;
import com.css.fxfzypg.modules.rating.library.model.vo.*;
import com.css.fxfzypg.modules.rating.library.service.cache.KpExamScoringDbCacheService;
import com.css.fxfzypg.modules.rating.library.service.cache.KpIndex3DataCacheService;
import com.css.fxfzypg.modules.rating.task.service.KpRatingTaskService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class KpExamScoringDbService {

    @Autowired
    private KpExamScoringDbIndex1Repository kpExamScoringDbIndex1Repository;
    @Autowired
    private KpExamScoringDbIndex2Repository kpExamScoringDbIndex2Repository;
    @Autowired
    private KpExamScoringDbIndex3Repository kpExamScoringDbIndex3Repository;
    @Autowired
    private KpExamScoringDbRepository kpExamScoringDbRepository;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private KpIndex3DataCacheService kpIndex3DataCacheService;
    public static final String CURR_USER_LATEST_CREATE_KPK = "ypg:currUserLatestCreateKpk";
    @Autowired
    KpExamIndex3PeekDataDao kpExamIndex3PeekDataDao;
    @Autowired
    KpRatingTaskService kpRatingTaskService;
    @Autowired
    KpExamScoringDbCacheService kpExamScoringDbCacheService;

    /**
     * 指标应用
     *
     * @param indexDto
     * @param currUid
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public KpExamScoringDbInsertIndexDto applyIndex(KpExamScoringDbInsertIndexDto indexDto, String currUid) {
        for (KpExamScoringDbInsertIndexListDto dto : indexDto.getIndexList()) {
            KpExamScoringDbIndex1 kpExamScoringDbIndex1 = kpExamScoringDbIndex1Repository.getById(dto.getIndex1Id());
            KpExamScoringDbIndex2 kpExamScoringDbIndex2 = kpExamScoringDbIndex2Repository.getById(dto.getIndex2Id());
            KpExamScoringDbIndex3 kpExamScoringDbIndex3 = kpExamScoringDbIndex3Repository.getById(dto.getIndex3Id());
            if (kpExamScoringDbIndex1 != null) {
                kpExamScoringDbIndex1.setName(dto.getIndex1Name());
                kpExamScoringDbIndex1Repository.updateById(kpExamScoringDbIndex1);
            } else {
                kpExamScoringDbIndex1 = new KpExamScoringDbIndex1();
                kpExamScoringDbIndex1.setId(dto.getIndex1Id());
                kpExamScoringDbIndex1.setName(dto.getIndex1Name());
                kpExamScoringDbIndex1.setCreateTime(new Date());
                kpExamScoringDbIndex1.setKesdId(indexDto.getKesdId());
                kpExamScoringDbIndex1Repository.insert(kpExamScoringDbIndex1);
            }
            if (kpExamScoringDbIndex2 != null) {
                kpExamScoringDbIndex2.setName(dto.getIndex2Name());
                kpExamScoringDbIndex2Repository.updateById(kpExamScoringDbIndex2);
            } else {
                kpExamScoringDbIndex2 = new KpExamScoringDbIndex2();
                kpExamScoringDbIndex2.setId(dto.getIndex2Id());
                kpExamScoringDbIndex2.setName(dto.getIndex2Name());
                kpExamScoringDbIndex2.setKpesdi1Id(kpExamScoringDbIndex1.getId());
                kpExamScoringDbIndex2.setCreateTime(new Date());
                kpExamScoringDbIndex2.setKpesdi1Id(kpExamScoringDbIndex1.getId());
                kpExamScoringDbIndex2Repository.insert(kpExamScoringDbIndex2);
            }
            if (kpExamScoringDbIndex3 != null) {
                kpExamScoringDbIndex3.setKpi3dId(dto.getIndex3Kpi3dId());
                kpExamScoringDbIndex3.setScore(dto.getIndex3Score());
                kpExamScoringDbIndex3.setIndexStandard(dto.getIndex3Standard());
                kpExamScoringDbIndex3Repository.updateById(kpExamScoringDbIndex3);
            } else {
                kpExamScoringDbIndex3 = new KpExamScoringDbIndex3();
                kpExamScoringDbIndex3.setId(IdUtil.simpleUUID());
                kpExamScoringDbIndex3.setKpi3dId(dto.getIndex3Kpi3dId());
                kpExamScoringDbIndex3.setScore(dto.getIndex3Score());
                kpExamScoringDbIndex3.setCreateTime(new Date());
                kpExamScoringDbIndex3.setKpesdi2Id(kpExamScoringDbIndex2.getId());
                kpExamScoringDbIndex3.setIndexStandard(dto.getIndex3Standard());
                kpExamScoringDbIndex3Repository.insert(kpExamScoringDbIndex3);
                KpIndex3Data kpIndex3Data = kpIndex3DataCacheService.getById(dto.getIndex3Kpi3dId());
                if (kpIndex3Data != null && kpIndex3Data.getCode() != null && kpIndex3Data.getCode().equals("26") && StringUtils.isNotBlank(dto.getPtgxTypeCodes())) {
                    String[] typeCode = dto.getPtgxTypeCodes().split(",");
                    for (String code : typeCode) {
                        KpExamIndex3PeekData peekData = new KpExamIndex3PeekData();
                        peekData.setId(IdUtil.simpleUUID());
                        peekData.setKesdi3Id(kpExamScoringDbIndex3.getId());
                        peekData.setDataTypeCode(code);
                        peekData.setCreateTime(new Date());
                        peekData.setCreateUser(currUid);
                        kpExamIndex3PeekDataDao.insert(peekData);
                    }
                }
            }
            dto.setIndex1Id(kpExamScoringDbIndex1.getId());
            dto.setIndex2Id(kpExamScoringDbIndex2.getId());
            dto.setIndex3Id(kpExamScoringDbIndex3.getId());
        }
        return indexDto;
    }

    public KpExamScoringDbInserIndexCacheDto findLatestCreateKpkFromCache(String currUid) {
        HashOperations<String, String, KpExamScoringDbInserIndexCacheDto> hashOps = redisTemplate.opsForHash();
        KpExamScoringDbInserIndexCacheDto kpExamScoringDbInserIndexCacheDto = hashOps.get(CURR_USER_LATEST_CREATE_KPK, currUid);
        if (kpExamScoringDbInserIndexCacheDto == null) {
            kpExamScoringDbInserIndexCacheDto = new KpExamScoringDbInserIndexCacheDto();
            kpExamScoringDbInserIndexCacheDto.setKesdId(IdUtil.simpleUUID());
        }
        return kpExamScoringDbInserIndexCacheDto;
    }

    /**
     * 删除指标
     *
     * @param index3Id
     */
    public void deleteIndexById(String index3Id) {
        KpExamScoringDbIndex3 kpExamScoringDbIndex3 = kpExamScoringDbIndex3Repository.getById(index3Id);
        kpExamScoringDbIndex3Repository.deleteById(kpExamScoringDbIndex3.getId());
        if (kpExamScoringDbIndex3Repository.countByKpesdi2Id(kpExamScoringDbIndex3.getKpesdi2Id()) == 0) {
            KpExamScoringDbIndex2 kpExamScoringDbIndex2 = kpExamScoringDbIndex2Repository.getById(kpExamScoringDbIndex3.getKpesdi2Id());
            kpExamScoringDbIndex2Repository.deleteById(kpExamScoringDbIndex2.getId());
            if (kpExamScoringDbIndex2Repository.countByKpesdi1Id(kpExamScoringDbIndex2.getKpesdi1Id()) == 0) {
                kpExamScoringDbIndex1Repository.deleteById(kpExamScoringDbIndex2.getKpesdi1Id());
            }
        }
    }

    public List<KpExamScoringDbListVo> list(KpExamScoringDb param) {
        List<KpExamScoringDb> list = kpExamScoringDbRepository.list(param);
        if (list != null) {
            return list.stream().map(kpk -> {
                KpExamScoringDbListVo vo = new KpExamScoringDbListVo();
                int useInfo = kpRatingTaskService.kpkIsUse(kpk.getId());
                BeanUtils.copyProperties(kpk, vo);
                vo.setIsUse(useInfo);
                return vo;
            }).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    public List<GetIndexListByKesdIdVo> listIndexByKesdId(String kesdId) {
        List<GetIndexListByKesdIdVo> resList = new ArrayList<>();
        KpExamScoringDbIndex1 index1Param = new KpExamScoringDbIndex1();
        index1Param.setKesdId(kesdId);
        List<KpExamScoringDbIndex1> index1List = kpExamScoringDbIndex1Repository.list(index1Param);
        for (KpExamScoringDbIndex1 index1 : index1List) {
            BigDecimal index1Score = kpExamScoringDbIndex3Repository.sumScoreByKesdi1Id(index1.getId());
            KpExamScoringDbIndex2 index2Param = new KpExamScoringDbIndex2();
            index2Param.setKpesdi1Id(index1.getId());
            List<KpExamScoringDbIndex2> index2List = kpExamScoringDbIndex2Repository.list(index2Param);
            for (KpExamScoringDbIndex2 kpExamScoringDbIndex2 : index2List) {
                KpExamScoringDbIndex3 index3Param = new KpExamScoringDbIndex3();
                index3Param.setKpesdi2Id(kpExamScoringDbIndex2.getId());
                List<KpExamScoringDbIndex3> index3List = kpExamScoringDbIndex3Repository.list(index3Param);
                double index2Score = index3List.stream().mapToDouble(o -> o.getScore().doubleValue()).sum();
                for (KpExamScoringDbIndex3 kpExamScoringDbIndex3 : index3List) {
                    GetIndexListByKesdIdVo indexVo = new GetIndexListByKesdIdVo();
                    indexVo.setIndex1Id(index1.getId());
                    indexVo.setIndex1Name(index1.getName());
                    indexVo.setIndex1Score(index1Score);
                    indexVo.setIndex2Id(kpExamScoringDbIndex2.getId());
                    indexVo.setIndex2Name(kpExamScoringDbIndex2.getName());
                    indexVo.setIndex2Score(BigDecimal.valueOf(index2Score));
                    indexVo.setIndex3Id(kpExamScoringDbIndex3.getId());
                    indexVo.setKpIndex3Data(kpIndex3DataCacheService.getById(kpExamScoringDbIndex3.getKpi3dId()));
                    indexVo.setIndex3Score(kpExamScoringDbIndex3.getScore());
                    indexVo.setIndex3Standard(kpExamScoringDbIndex3.getIndexStandard());
                    List<KpExamIndex3PeekData> peekDataList = kpExamIndex3PeekDataDao.selectByKesdi3id(kpExamScoringDbIndex3.getId());
                    if (peekDataList != null) {
                        indexVo.setPtgxTypeCodes(StringUtils.join(peekDataList.stream().map(KpExamIndex3PeekData::getDataTypeCode).collect(Collectors.toList()), ","));
                    }
                    resList.add(indexVo);
                }
            }
        }
        return resList;
    }

    /**
     * 删除考评库
     *
     * @param kesdId
     * @param currUid
     */
    public void deleteById(String kesdId, String currUid) throws Exception {
        Date currTime = new Date();
        if (ObjectUtils.isEmpty(kesdId)) {
            throw new Exception("考评库id不能为空");
        }
        kpExamScoringDbRepository.deleteById(kesdId, currUid, currTime);
        kpExamScoringDbCacheService.deleteById(kesdId);
    }

    public List<KpExamScoringDbIndex1Vo> getIndex(String kesdId) {
        KpExamScoringDbIndex1 index1Param = new KpExamScoringDbIndex1();
        index1Param.setKesdId(kesdId);
        List<KpExamScoringDbIndex1> index1List = kpExamScoringDbIndex1Repository.list(index1Param);
        List<KpExamScoringDbIndex1Vo> resList = new ArrayList<>();
        for (KpExamScoringDbIndex1 index1 : index1List) {
            KpExamScoringDbIndex1Vo kpExamScoringDbIndex1Vo = new KpExamScoringDbIndex1Vo();
            BeanUtils.copyProperties(index1, kpExamScoringDbIndex1Vo);
            KpExamScoringDbIndex2 index2Param = new KpExamScoringDbIndex2();
            index2Param.setKpesdi1Id(index1.getId());
            List<KpExamScoringDbIndex2> index2List = kpExamScoringDbIndex2Repository.list(index2Param);
            List<KpExamScoringDbIndex2Vo> index2VoList = new ArrayList<>();
            for (KpExamScoringDbIndex2 index2 : index2List) {
                KpExamScoringDbIndex2Vo kpExamScoringDbIndex2Vo = new KpExamScoringDbIndex2Vo();
                BeanUtils.copyProperties(index2, kpExamScoringDbIndex2Vo);
                List<KpExamScoringDbIndex3Vo> index3VoList = new ArrayList<>();
                KpExamScoringDbIndex3 index3Param = new KpExamScoringDbIndex3();
                index3Param.setKpesdi2Id(index2.getId());
                List<KpExamScoringDbIndex3> index3List = kpExamScoringDbIndex3Repository.list(index3Param);
                for (KpExamScoringDbIndex3 index3 : index3List) {
                    KpExamScoringDbIndex3Vo kpExamScoringDbIndex3Vo = new KpExamScoringDbIndex3Vo();
                    BeanUtils.copyProperties(index3, kpExamScoringDbIndex3Vo);
                    kpExamScoringDbIndex3Vo.setKpIndex3Data(kpIndex3DataCacheService.getById(index3.getKpi3dId()));
                    index3VoList.add(kpExamScoringDbIndex3Vo);
                }
                kpExamScoringDbIndex2Vo.setChildren(index3VoList);
                index2VoList.add(kpExamScoringDbIndex2Vo);
            }
            kpExamScoringDbIndex1Vo.setChildren(index2VoList);
            resList.add(kpExamScoringDbIndex1Vo);
        }
        return CollectionUtils.isEmpty(resList) ? null : resList;
    }

    public List<KpExamScoringDbIndex1Vo> getIndexByKrtytId(String krtytId) {
        List<KpExamScoringDbIndex1> index1List = kpExamScoringDbIndex1Repository.getByKrtytId(krtytId);
        List<KpExamScoringDbIndex1Vo> resList = new ArrayList<>();
        for (KpExamScoringDbIndex1 index1 : index1List) {
            KpExamScoringDbIndex1Vo kpExamScoringDbIndex1Vo = new KpExamScoringDbIndex1Vo();
            BeanUtils.copyProperties(index1, kpExamScoringDbIndex1Vo);
            KpExamScoringDbIndex2 index2Param = new KpExamScoringDbIndex2();
            index2Param.setKpesdi1Id(index1.getId());
            List<KpExamScoringDbIndex2> index2List = kpExamScoringDbIndex2Repository.list(index2Param);
            List<KpExamScoringDbIndex2Vo> index2VoList = new ArrayList<>();
            for (KpExamScoringDbIndex2 index2 : index2List) {
                KpExamScoringDbIndex2Vo kpExamScoringDbIndex2Vo = new KpExamScoringDbIndex2Vo();
                BeanUtils.copyProperties(index2, kpExamScoringDbIndex2Vo);
                List<KpExamScoringDbIndex3Vo> index3VoList = new ArrayList<>();
                KpExamScoringDbIndex3 index3Param = new KpExamScoringDbIndex3();
                index3Param.setKpesdi2Id(index2.getId());
                List<KpExamScoringDbIndex3> index3List = kpExamScoringDbIndex3Repository.list(index3Param);
                for (KpExamScoringDbIndex3 index3 : index3List) {
                    KpExamScoringDbIndex3Vo kpExamScoringDbIndex3Vo = new KpExamScoringDbIndex3Vo();
                    BeanUtils.copyProperties(index3, kpExamScoringDbIndex3Vo);
                    kpExamScoringDbIndex3Vo.setKpIndex3Data(kpIndex3DataCacheService.getById(index3.getKpi3dId()));
                    index3VoList.add(kpExamScoringDbIndex3Vo);
                }
                kpExamScoringDbIndex2Vo.setChildren(index3VoList);
                index2VoList.add(kpExamScoringDbIndex2Vo);
            }
            kpExamScoringDbIndex1Vo.setChildren(index2VoList);
            resList.add(kpExamScoringDbIndex1Vo);
        }
        return CollectionUtils.isEmpty(resList) ? null : resList;
    }

    public KpExamScoringDb getById(String kesdId) {
        return kpExamScoringDbRepository.getById(kesdId);
    }

    @Transactional(rollbackFor = Exception.class)
    public void updatePtgxType(KpUpdatePtgxTypeDto dto, String currUid) {
        String[] typeCode = dto.getPtgxTypeCodes().split(",");
        kpExamIndex3PeekDataDao.deleteByKesdi3Id(dto.getIndex3Id());
        for (String code : typeCode) {
            KpExamIndex3PeekData peekData = new KpExamIndex3PeekData();
            peekData.setId(IdUtil.simpleUUID());
            peekData.setKesdi3Id(dto.getIndex3Id());
            peekData.setDataTypeCode(code);
            peekData.setCreateTime(new Date());
            peekData.setCreateUser(currUid);
            kpExamIndex3PeekDataDao.insert(peekData);
        }
    }
}
